/*************PIN****************
  CubeMX 定义任意两个引脚，作为通讯脚，并对引脚作出如下配置：
  GPlO output level       －－High
  GPIO mode               －－Output open drai
  GPIO Pull-up/Pull-down  －－No pull-up and no pull-down
  Maximum output speed    －－LOW
  User label              －－IIC_SCL/IIC_SDA
***********************************/
#include "IIC_SoftSimu.h"


#define	 GPIO_WRITE_PIN(PORT,PIN,VALUE)	HAL_GPIO_WritePin(PORT,PIN,(VALUE)?GPIO_PIN_SET:GPIO_PIN_RESET)
#define	 GPIO_READ_PIN(PORT,PIN)		HAL_GPIO_ReadPin(PORT,PIN)


typedef enum  {
  IIC_OK           = 0x00,    //IIC工作正常
  IIC_WAIT_ACK_ERR = 0x01,    //slave设备返回ACK错误
  IIC_WRITE_ERR    = 0x02,    //向slave设备写入错误
  IIC_READ_ERR     = 0x04     //从slave设备读取错误
} IIC_STATUS;


inline void IIC_Delay(volatile uint32_t cnt)
{
  while(--cnt);
}

inline void IIC_Init(const Soft_IIC* hSIIC)
{
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 1);
}

inline void IIC_Start(const Soft_IIC* hSIIC)
{
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 0);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 0);
  IIC_Delay(hSIIC->Delaycnt);
}

inline void IIC_Stop(const Soft_IIC* hSIIC)
{
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 0);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
}

inline IIC_STATUS IIC_Wait_ACK(const Soft_IIC* hSIIC)
{
  uint8_t s1;
  uint8_t i = 0;

  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);

  s1 = GPIO_READ_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin);
  while (s1 && i++ < 100) //判断是否应答 0应答，1无答
  {
	s1 = GPIO_READ_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin);
  }

  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 0);
  IIC_Delay(hSIIC->Delaycnt);

  if(s1)
    return (IIC_WAIT_ACK_ERR);
  else
    return (IIC_OK);
}

inline void IIC_ACK(const Soft_IIC* hSIIC)
{
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 0);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 0);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
}
inline void IIC_NACK(const Soft_IIC* hSIIC)
{
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
  GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 0);
  IIC_Delay(hSIIC->Delaycnt);
}

void IIC_WriteByte(const Soft_IIC* hSIIC, uint8_t data)
{
  for(uint32_t i=0; i < 8; ++i)
  {
    GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, ((data & 0x80) == 0x80) ?1 :0);
    IIC_Delay(hSIIC->Delaycnt);
    data <<= 1;
    GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
    IIC_Delay(hSIIC->Delaycnt);
    GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 0);
    IIC_Delay(hSIIC->Delaycnt);
  }
  GPIO_WRITE_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin, 1);
  IIC_Delay(hSIIC->Delaycnt);
}

void IIC_ReadByte(const Soft_IIC* hSIIC,uint8_t *data)
{
  uint8_t tmp=0;

  for(uint32_t i=0; i<8; ++i)
  {
    tmp <<= 1;
    GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 1);
    IIC_Delay(hSIIC->Delaycnt);
    if(GPIO_READ_PIN(hSIIC->SDA_Port, hSIIC->SDA_Pin))
      tmp = tmp | 0x01;
    else
      tmp = tmp | 0xFE;
    GPIO_WRITE_PIN(hSIIC->SCL_Port, hSIIC->SCL_Pin, 0);
    IIC_Delay(hSIIC->Delaycnt);
  }
  *data = tmp;
}

